using Dapper;
using MediatR;
using NPOI.SS.UserModel;
using NPOI.XSSF.UserModel;
using RBAC.Domain.Dto.Output;
using RBAC.Domain.ProcessManagement;
using RBAC.ErrorCode;
using RBAC.Interstructrue.Base;
using RBAC.Read.Api.Application.Command.ProcessManagements;

namespace RBAC.Read.Api.Application.Handler.ProcessManagements
{
    /// <summary>
    /// 工序列表导出处理器（读端）
    /// </summary>
    public class ExportProcessesHandler : IRequestHandler<ExportProcessesCommand, APIResult<byte[]>>
    {
        private readonly IBaseRepository<ProcessInfo> _repo;

        public ExportProcessesHandler(IBaseRepository<ProcessInfo> repo)
        {
            _repo = repo;
        }

        public async Task<APIResult<byte[]>> Handle(ExportProcessesCommand request, CancellationToken cancellationToken)
        {
            try
            {
                var (where, param) = BuildWhere(request);

                var dataSql = $@"SELECT
                                    pi.Id,
                                    pi.ProcessCode,
                                    pi.ProcessName,
                                    pi.SystemCode,
                                    pi.ClassificationId,
                                    COALESCE(pc.ClassificationName, pi.ClassificationName) AS ClassificationName,
                                    pi.DepartmentId,
                                    COALESCE(dm.DepartmentName, pi.DepartmentName) AS DepartmentName,
                                    pi.OwnerUserId,
                                    COALESCE(u.UserName, pi.OwnerUserName) AS OwnerUserName,
                                    pi.Status,
                                    pi.Remark,
                                    pi.CreateTime,
                                    pi.CreateUser
                                  FROM ProcessInfo pi
                                  LEFT JOIN ProcessClassification pc ON pi.ClassificationId = pc.Id AND pc.IsDeleted = 0
                                  LEFT JOIN Department dm ON pi.DepartmentId = dm.Id AND dm.IsDeleted = 0
                                  LEFT JOIN `User` u ON pi.OwnerUserId = u.Id AND u.IsDeleted = 0
                                  {(string.IsNullOrWhiteSpace(where) ? "" : "WHERE " + where)}
                                  ORDER BY {request.OrderBy}";

                var rows = _repo.Query<ProcessListDto>(dataSql, param)?.ToList() ?? new List<ProcessListDto>();
                if (rows.Count == 0)
                {
                    return new APIResult<byte[]>
                    {
                        Code = APIEnums.Fail,
                        Msg = "没有可导出的工序数据",
                        Data = Array.Empty<byte>()
                    };
                }

                var wb = new XSSFWorkbook();
                var sheet = wb.CreateSheet("工序");

                var headers = new[] { "工序编号", "工序名称", "工序分类", "负责人", "所属部门", "状态", "备注", "创建时间", "创建人" };
                var headerRow = sheet.CreateRow(0);
                for (int i = 0; i < headers.Length; i++) headerRow.CreateCell(i).SetCellValue(headers[i]);

                for (int r = 0; r < rows.Count; r++)
                {
                    var m = rows[r];
                    var row = sheet.CreateRow(r + 1);
                    row.CreateCell(0).SetCellValue(m.ProcessCode ?? string.Empty);
                    row.CreateCell(1).SetCellValue(m.ProcessName ?? string.Empty);
                    row.CreateCell(2).SetCellValue(m.ClassificationName ?? string.Empty);
                    row.CreateCell(3).SetCellValue(m.OwnerUserName ?? string.Empty);
                    row.CreateCell(4).SetCellValue(m.DepartmentName ?? string.Empty);
                    row.CreateCell(5).SetCellValue(m.Status == 1 ? "启用" : "禁用");
                    row.CreateCell(6).SetCellValue(m.Remark ?? string.Empty);
                    row.CreateCell(7).SetCellValue(m.CreateTime?.ToString("yyyy-MM-dd HH:mm:ss") ?? string.Empty);
                    row.CreateCell(8).SetCellValue(m.CreateUser ?? string.Empty);
                }

                using var ms = new MemoryStream();
                wb.Write(ms);
                ms.Flush();
                var bytes = ms.ToArray();

                return new APIResult<byte[]>
                {
                    Code = APIEnums.Success,
                    Msg = $"成功导出{rows.Count}条数据",
                    Data = bytes
                };
            }
            catch (Exception ex)
            {
                return new APIResult<byte[]>
                {
                    Code = APIEnums.Fail,
                    Msg = "导出失败：" + ex.Message,
                    Data = Array.Empty<byte>()
                };
            }
        }

        private static (string where, DynamicParameters param) BuildWhere(ExportProcessesCommand req)
        {
            var conds = new List<string> { "pi.IsDeleted = 0" };
            var p = new DynamicParameters();

            if (!string.IsNullOrWhiteSpace(req.Keyword))
            {
                conds.Add("(pi.ProcessCode LIKE @kw OR pi.ProcessName LIKE @kw)");
                p.Add("@kw", $"%{req.Keyword}%");
            }
            if (req.ClassificationId.HasValue)
            {
                conds.Add("pi.ClassificationId = @ClassificationId");
                p.Add("@ClassificationId", req.ClassificationId.Value);
            }
            if (req.DepartmentId.HasValue)
            {
                conds.Add("pi.DepartmentId = @DepartmentId");
                p.Add("@DepartmentId", req.DepartmentId.Value);
            }
            if (req.Status.HasValue)
            {
                conds.Add("pi.Status = @Status");
                p.Add("@Status", req.Status.Value);
            }

            var where = string.Join(" AND ", conds);
            return (where, p);
        }
    }
}
